package com.weixiaodong.ModelDesign.生成实例.Singleton模式.静态与私有化构造方法;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class SingletonA {

    private static final SingletonA singleton = new SingletonA(); // static修饰的类型只会在类加载的时候加载一次，之后就不会加载了


    private SingletonA() {}; // 私有化构造方法是为了不让外部直接通过new的方式创建对象, 但是这种方式实际上可以被反射破坏，所以并不是一个安全的单例模式


    public static SingletonA getInstance() { // 对外暴露的一个获取单例的入口， 因为构造方法被私有化了，所以我们无法通过实例对象去调用，所以该方法需要设置为static的，即可以通过类名调用
        return singleton;
    }

    public static void main(String[] args) {

        //SingletonA instance1 = SingletonA.getInstance();
        //SingletonA instance2 = SingletonA.getInstance();
        //System.out.println(instance1 == instance2); // true

        // 演示反射破坏单例
        Class<SingletonA> singletonAClass = SingletonA.class;
        Constructor<?>[] declaredConstructors = singletonAClass.getDeclaredConstructors();
        Constructor<?> declaredConstructor = declaredConstructors[0];
        // declaredConstructor.setAccessible(true);
        try {
            SingletonA instance1 = (SingletonA) declaredConstructor.newInstance();
            SingletonA instance2 = (SingletonA) declaredConstructor.newInstance();
            System.out.println(instance1 == instance2); // false, 因为通过发射我们可以在运行时获取类的私有构造方法，然后通过该方法创建实例对象
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
